/*
 * Project CHEN Rendering Engine : /utils.hpp
 * Created: 2020-12-16, Last modified:  2021-01-27
 * 
 * This header file containes declarations of data structures needed
 * in the process of rendering.
 * 
 * Copyright (C) 2021 Hineven (hineven@pku.edu.cn)
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */



#ifndef _H_SCENE
#define _H_SCENE
#include "heads.hpp"
#include "object.hpp"
#include "light.hpp"
#include "shape.hpp"
#include "flags.hpp"
#include "strc.hpp"
namespace chen {
/**
 * The structure to contain all objects and lights during rendering.
 * While all the elements it holds should remain constant.
 */
class Scene {
public:
	const Structure * all;
	std::vector<const Light *> lights;
	std::vector<const AreaLight *> arealights;
	Float * light_power_series;
	Float * light_area_series;
	/**
	 * Initialize a scene for rendering.
	 * Notice that all the objects that referred by the pointers passed in WILL
	 * NOT be automatically destroyed inside the class destructor '~Scene()'. 
	 */
	Scene(const Structure * s, const std::vector<const Light *> & lights) ;
	inline ~Scene () {
		delete [] light_power_series;
		delete [] light_area_series;
	}
	inline bool castRay (const Ray & r, SurfInteract * si) const {
		return all->castRay(r, si);
	}
	// 测试一条射线是否与任何物体相交
	inline const Shape * testRay (const Ray & r) const {
		return all->testRay(r);
	}
	inline const Light * randomPickLight() const 
	{
		return this->lights[rand()%this->lights.size()];
	}
	inline const AreaLight * randomPickAreaLight() const 
	{
		int x = rand()%this->arealights.size();
		return (AreaLight*)this->arealights[x];
	}
	const Light * pickLightRespectToArea (const Float & u, Float * pdf) const ;
	const Light * pickLightRespectToPower (const Float & u, Float * pdf) const ;
};
}
#endif
